package com.xg.frame.components;

import com.xg.sys.entity.SysDictionary;
import com.xg.sys.service.SysDictionaryService;
import com.xg.sys.vo.SelectVO;
import com.xg.frame.entity.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IModelFactory;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.AbstractElementTagProcessor;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import org.thymeleaf.templatemode.TemplateMode;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * @author tzt
 * @date Created in 2021/8/11 14:10
 * @description：自定义下拉
 * @modified By：
 */
@Component
@Slf4j
public class SqSelect extends AbstractElementTagProcessor {
    @Resource
    private SysDictionaryService sysDictionaryService;
    @Resource
    private ApplicationContext ac;
    /**
     * 优先级
     */
    private static final int PRECEDENCE = 10000;
    /**
     * 标签名
     */
    private static final String TAG_NAME = "select";

    private void optionForUrl(String value, String url, StringBuilder sb) {
        RequestMappingHandlerMapping mapping = ac.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = mapping.getHandlerMethods();
        handlerMethods.forEach((x, y) -> {
            if (x.getPatternsCondition().getPatterns().stream().anyMatch(item -> item.equals(url))) {
                try {
                    R<List<SelectVO>> invoke = (R<List<SelectVO>>) y.getMethod().invoke(ac.getBean(y.getBeanType()));
                    invoke.getInfo().forEach(item -> {
                        sb.append("<option value='").append(item.getCode()).append("'");
                        if (StringUtils.isNotBlank(value) && value.equals(item.getCode())) {
                            sb.append(" selected");
                        }
                        sb.append(">").append(item.getName()).append("</option>");
                    });
                } catch (Exception e) {
                    log.error("通过url:{}自定义select失败", url, e);
                }
            }
        });

    }

    public SqSelect() {
        super(
                // 模板类型为HTML
                TemplateMode.HTML,
                // 标签方言前缀
                CustomComponents.PREFIX,
                // 标签名称
                TAG_NAME,
                // 将标签前缀应用于标签名称
                true,
                // 无属性名称：将通过标签名称匹配
                null,
                // 没有要应用于属性名称的前缀
                false,
                // 优先级
                PRECEDENCE
        );
    }

    /**
     * 处理自定义标签 DOM 结构
     *
     * @param iTemplateContext            模板页上下文
     * @param iProcessableElementTag      待处理标签
     * @param iElementTagStructureHandler 元素标签结构处理器
     */
    @Override
    protected void doProcess(ITemplateContext iTemplateContext, IProcessableElementTag iProcessableElementTag, IElementTagStructureHandler iElementTagStructureHandler) {
        String sqSelect = "<select class='form-control' id='%s' name='%s' value='%s' %s>%s</select>";
        //select的id属性
        String id = iProcessableElementTag.getAttributeValue("id");
        //select的name属性
        String name = iProcessableElementTag.getAttributeValue("name");
        //默认值
        String value = iProcessableElementTag.getAttributeValue("value");
        //字典码
        String dicCode = iProcessableElementTag.getAttributeValue("dicCode");
        //请求路径
        String url = iProcessableElementTag.getAttributeValue("url");
        //占位符
        String pleaseChoose = iProcessableElementTag.getAttributeValue("pleaseChoose");
        StringBuilder sb = new StringBuilder().append(StringUtils.isBlank(pleaseChoose) ? "" : "<option value=''>请选择" + pleaseChoose + "</option>");
        if (StringUtils.isNotBlank(dicCode)) {
            optionForDicCode(value, dicCode, sb);
        } else if (StringUtils.isNotBlank(url)) {
            optionForUrl(value, url, sb);
        }

        sqSelect = String.format(sqSelect, id, name, value == null ? "" : value, iProcessableElementTag.hasAttribute("required") ? "required" : "", sb.toString());
        // 创建将替换自定义标签的 DOM 结构
        IModelFactory modelFactory = iTemplateContext.getModelFactory();
        IModel model = modelFactory.createModel();
        // 这里是将字典的内容拼装成一个下拉框
        model.add(modelFactory.createText(sqSelect));
        // 利用引擎替换整合标签
        iElementTagStructureHandler.replaceWith(model, false);


        /*
        // 获取 Spring 上下文
        ApplicationContext applicationContext = SpringContextUtils.getApplicationContext(iTemplateContext);
        // 获取注入bean工厂
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        // 获取所需的bean，一般情况下这里我们直接使用Jdbc来操作数据库，因为它是一个公共组件，数据源不确定，所以要使用动态sql
        JdbcOperations jdbcOperations = autowireCapableBeanFactory.getBean(JdbcOperations.class);
        //select的id属性
//        String id = iProcessableElementTag.getAttributeValue("id");
        //select的name属性
//        String name = iProcessableElementTag.getAttributeValue("name");
        //option中value的值在数据表中的对应字段
        String colVal = iProcessableElementTag.getAttributeValue("colVal");
        //option中文本的值在数据表中的对应字段
        String colText = iProcessableElementTag.getAttributeValue("colText");
        //默认值
//        String value = iProcessableElementTag.getAttributeValue("value");
        value = StringUtils.isBlank(value) ? "" : value;
        //select的扩展属性
        String otherAttrs = iProcessableElementTag.getAttributeValue("otherAttrs");
        //sql where之后的部分
        String options = iProcessableElementTag.getAttributeValue("options");
        //是否显示请选择
        String selectFlag = iProcessableElementTag.getAttributeValue("selectFlag");
        //表名称
        String tableName = iProcessableElementTag.getAttributeValue("tableName");
        StringBuffer result = new StringBuffer("<select><option value=''>--请选择--</option></select>");
        if(validParamIsNotNull(id,name,colText, colVal, tableName)) {
            //最终拼接的sql语句，这里可以使用jdbc来查询
            String selectSql = "select " + colVal + "," + colText + " from " + tableName + options;
            List<Map<String, Object>> mapList = jdbcOperations.queryForList(selectSql);
            if (mapList != null && mapList.size() >= 0) {
                result = new StringBuffer("<select ");
                result.append(" id='").append(id).append("'");
                result.append(" name='").append(name).append("'");
                if(StringUtils.isNotBlank(otherAttrs)) {
                    result.append(" " + otherAttrs +" ");
                }
                result.append(">");
                if(StringUtils.isBlank(selectFlag) || (StringUtils.isNotBlank(selectFlag) && "true".equalsIgnoreCase(selectFlag))) {
                    result.append("<option value=''>--请选择--</option>");
                }
                for (Map<String, Object> vo : mapList) {
                    String dictValue = MapUtils.getString(vo, colVal);
                    String dictName = MapUtils.getString(vo, colText);
                    if (value.equals(dictValue)) {
                        result.append("<option value='").append(dictValue).append("' selected>").append(dictName).append("</option>");
                    } else {
                        result.append("<option value='").append(dictValue).append("'>").append(dictName).append("</option>");
                    }
                }
                result.append("</select>");
            }
        }
        // 创建将替换自定义标签的 DOM 结构
        IModelFactory modelFactory = iTemplateContext.getModelFactory();
        IModel model = modelFactory.createModel();
        // 这里是将字典的内容拼装成一个下拉框
        model.add(modelFactory.createText(result));
        // 利用引擎替换整合标签
        iElementTagStructureHandler.replaceWith(model, false);*/
    }


    private void optionForDicCode(String value, String dicCode, StringBuilder sb) {
        List<SysDictionary> dicList = sysDictionaryService.getDiclist(dicCode);
        dicList.stream().forEach(item -> {
            sb.append("<option value='").append(item.getDataCode()).append("'");
            if (StringUtils.isNotBlank(value) && value.equals(item.getDataCode())) {
                sb.append(" selected");
            }
            sb.append(">").append(item.getDataName()).append("</option>");
        });
    }

    /**
     * 验证参数是否不为空
     *
     * @param params
     * @return true, 不为空；false，为空
     */
    public static Boolean validParamIsNotNull(String... params) {
        for (String param : params) {
            if (StringUtils.isBlank(param)) {
                return false;
            }
        }
        return true;
    }
}
